package com.zyht.common.excel;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class DefaultExcelImportBean<T> implements IImport<T> {
	
	private Logger logger = LoggerFactory.getLogger(getClass());
	
	private Integer batchSize = 1000;
	
	private IPersist<T> persist;
	
	@Override
	public int doImport(InputStream is, Class<T> clazz) throws InvalidFormatException, IOException{
		
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		
		Workbook book = WorkbookFactory.create(is);
		Sheet sheet = book.getSheetAt(0);
		int totalRow = sheet.getLastRowNum();
		
		int startRow = 1;
		Field[] fieldArray = clazz.getDeclaredFields();
		Map<String, Type> fieldClassMap = new HashMap<>();
		Map<String, Field> fieldMap = new HashMap<>();
		for(Field field : fieldArray){
			if(!field.isAnnotationPresent(Column.class)){
				continue;
			}
			Column column = field.getAnnotation(Column.class);
			fieldClassMap.put("key_"+column.index(), field.getGenericType());
			fieldMap.put("key_"+column.index(), field);
		}
		int readTotal = 0;
		int endIndex = 0;
		if((batchSize+1)<totalRow){
			endIndex = batchSize+1;
		}else{
			endIndex = totalRow;
		}
		while(startRow<=totalRow){
			List<T> list = new ArrayList<T>();
			T bean = null;
			for(int index = startRow; index<=endIndex; index++){
				Row row = sheet.getRow(index);
				if(null!=row.getCell(0) && row.getCell(0).getCellType()==Cell.CELL_TYPE_BLANK){
					continue;
				}
				try{
					bean = clazz.newInstance();
				} catch (InstantiationException e){
					e.printStackTrace();
				} catch (IllegalAccessException e){
					e.printStackTrace();
				}
				if(null==bean){
					continue;
				}
				Iterator<Cell> it = row.cellIterator();
				while(it.hasNext()){
					Cell cell = it.next();
					int cellIndex = cell.getColumnIndex();
					Type type = fieldClassMap.get("key_"+cellIndex);
					Field field = fieldMap.get("key_"+cellIndex);
					field.setAccessible(true);
					int cellType = cell.getCellType();
					try{
						if(cellType == Cell.CELL_TYPE_BLANK || cellType == Cell.CELL_TYPE_ERROR){
							field.set(bean,null);
						}else if(cellType == Cell.CELL_TYPE_BOOLEAN){
							boolean value = cell.getBooleanCellValue();
							if(type.getTypeName().equals(String.class.getTypeName())){
								field.set(bean, value+"");
							}else if(type.getTypeName().equals(Integer.class.getTypeName())){
								field.set(bean, value?1:0);
							}else if(type.getTypeName().equals(Float.class.getTypeName())){
								field.set(bean, value?1l:0l);
							}else if(type.getTypeName().equals(Double.class.getTypeName())){
								field.set(bean, value?1d:0d);
							}else if(type.getTypeName().equals(Boolean.class.getTypeName())){
								field.set(bean, value);
							}else{
								field.set(bean, null);
							}
						}else if(cellType == Cell.CELL_TYPE_NUMERIC){
							cell.setCellType(Cell.CELL_TYPE_STRING);
						}
						
						if(cellType == Cell.CELL_TYPE_STRING){
							String value = cell.getStringCellValue();
							if(type.getTypeName().equals(String.class.getTypeName())){
								field.set(bean, value);
							}else if(type.getTypeName().equals(Integer.class.getTypeName())){
								field.set(bean, Integer.valueOf(value));
							}else if(type.getTypeName().equals(Float.class.getTypeName())){
								field.set(bean, Float.valueOf(value));
							}else if(type.getTypeName().equals(Double.class.getTypeName())){
								field.set(bean, Double.valueOf(value));
							}else if(type.getTypeName().equals(Date.class.getTypeName())){
								try{
									field.set(bean, sf.parseObject(value));
								} catch (ParseException e){
									e.printStackTrace();
									field.set(bean, null);
									logger.error("在excel中的日期字符串无法转换成指定日期类型！");
								}
							}else{
								field.set(bean, null);
							}
						}
						readTotal ++;
					} catch (IllegalArgumentException e){
						e.printStackTrace();
						continue;
					} catch (IllegalAccessException e){
						e.printStackTrace();
						continue;
					}
				}
				list.add(bean);
			}
			startRow = endIndex +1;
			if(endIndex+batchSize <= totalRow){
				endIndex = totalRow;
			}else{
				endIndex += batchSize;
			}
			if(list.size()>0){
				persist.doPersist(list);
			}
			logger.info("已导入数据："+ batchSize);
		}
		book.close();
		is.close();
		return readTotal;
	}
	
	public void setBatchSize(Integer batchSize){
		if(null!=batchSize){
			this.batchSize = batchSize;
		}
	}

	public void setPersist(IPersist<T> persist){
		this.persist = persist;
	}
}
